#ifndef MATRICE_H
#define MATRICE_H
/**
 * \file Matrice.h
 * \brief Définit une Matrice
 *
 */

#include <cstddef> // NULL

#include "vecteur.h"

/*! \class Masque
* \brief Classe Matrice
*
*  La classe permet l'utilisation de matrices et d'effectuer des operations sur celles ci.
*/

class Matrice
{
	public :
			
		Matrice ( int largeur, int hauteur );
		Matrice ( int largeur, int hauteur, float** _matrice );
		Matrice ( int largeur, int hauteur, float* _matrice );
		
		~Matrice ();
	
	/*!
	 *  \brief Calcule la trace de la matrice
	 *	
	 *  Methode qui permet calculer la trace d'une matrice
	 *  \return Retourne la trace de la matrice
	 */	
		float trace ();
		
	/*!
	 *  \brief Surcharge d'operateur : multiplier deux matrices entre elles
	 *
	 *  Applique this x m
	 *  \param _m la matrice de droite (bouh !)
	 *  \param _res la matrice résultat (si NULL alors elle sera créée)
	 *  \return Retourne un pointeur vers la matrice resultat.
	 */	
		Matrice* multiplication ( Matrice* m, Matrice * resultat = NULL );
		
	/*!
	 *  \brief Multiplie une matrice par un flottant
	 *
	 *  Applique a x this
	 *  \param _x le coefficient
	 *  \param _res la matrice résultat (si NULL alors elle sera créée)
	 *  \return Retourne un pointeur vers la matrice resultat.
	 */	
		Matrice* multiplication ( float _x, Matrice * _res = NULL );
	
	/*!
	 *  \brief Surcharge d'operateur : additionner deux matrices
	 *
	 *  Methode qui permet d'additionner deux matrices
	 *  \param m la deuxieme matrice à additionner
	 *  \param resultat pointeur vers la matrice résultat (créée si NULL)
	 *  \return Retourne un pointeur vers la matrice resultat.
	 */	
		Matrice* addition  ( Matrice* m, Matrice * resultat = NULL );
		
	/*!
	 *  \brief Surcharge d'operateur : soustraire deux matrices
	 *
	 *  Methode qui permet de soustraire deux matrices
	 *  \return Retourne un pointeur vers la matrice resultat.
	 */
		Matrice* soustraction  ( Matrice* m );
		
	/*!
	 *  \brief Renvoie la valeur propre maximale de la matrice 2x2
	 *
	 *  Methode qui calcule la valeur propre maximale d'une matrice 2x2
	 *  \return Retourne la valeur propre maximale de la matrice 2x2
	 */	
		float valeurPropreMax ();
				
	/*!
	 *  \brief Renvoie la valeur propre minimale de la matrice 2x2
	 *
	 *  Methode qui calcule la valeur propre minimale d'une matrice 2x2
	 *  \return Retourne la valeur propre minimale de la matrice 2x2
	 */	
		float valeurPropreMin ();
		
	/*!
	 *  \brief Calcule les valeurs propres de la matrice
	 *
	 *  Les valeurs propres de la matrice sont les racines de l'équation det(M-xI) = 0.
	 *  \param _lambda1 pointeur vers la première valeur propre à remplir
	 *  \param _lambda1 pointeur vers la deuxième valeur propre à remplir
	 *  \return 0 si les valeurs propres ont pu être calculées, -1 sinon
	 */		
		int valeursPropres ( float * _lambda1, float * _lambda2 );
		
	/*!
	 *  \brief Renvoie le vecteur propre de la matrice engendré par la valeur propre maximale 2x2
	 *
	 *  Methode qui calcule le vecteur propre de la matrice engendré par la valeur propre maximale 2x2
	 *  \return Retourne le vecteur propre de la matrice engendré par la valeur propre maximale 2x2
	 */	
		Matrice* vecteurPropreMin ();
		
	/*!
	 *  \brief Renvoie le vecteur propre de la matrice engendré par la valeur propre minimale 2x2
	 *
	 *  Methode qui calcule le vecteur propre de la matrice engendré par la valeur propre minimale 2x2
	 *  \return Retourne le vecteur propre de la matrice engendré par la valeur propre minimale 2x2
	 */	
		Matrice* vecteurPropreMax ();
		
	/*!
	 *  \brief Renvoie le vecteur propre de la matrice 2x2 donnée, correspondant à la valeur propre donnée
	 *
	 *  Utilise la règle de Cramer pour résoudre le système.
	 *  \param _lambda la valeur propre
	 *  \param _res la matrice 1 colonne et 2 lignes résultante (créée si NULL)
	 *  \param _err si != NULL, contiendra -1 si le vecteur propre n'a pas pu être calculé
	 *  \return un pointeur vers la matrice 1 colonne et 2 lignes résultante
	 */	
		Matrice * vecteurPropre ( float _lambda, Matrice * _res = NULL,
			int * _err = NULL );
		
	/*!
	 *  \brief Calcule les valeurs et vecteurs propres de la matrice
	 *
	 *  Les valeurs résultats sont stockées dans les pointeurs de variables donnés en paramètre.
	 *  \param _lambda1 la valeur propre 1
	 *  \param _lambda2 la valeur propre 2
	 *  \param _theta1 la matrice (1 colonne et 2 lignes) du vecteur propre 1
	 *  \param _theta2 la matrice (1 colonne et 2 lignes) du vecteur propre 2
	 *  \return 0 si succès, -1 si échec
	 */		
		int calculValEtVecPropres ( float * _lambda1, float * _lambda2,
			Matrice * _theta1, Matrice * _theta2 );
		
	/*!
	 *  \brief Renvoie la valeur de la matrice en (i,j)
	 *
	 *  Methode qui envoie la valeur de la matrice en (i,j)
	 *  \param i : coordonnée ("abscisse") de la valeur cherchee dans la matrice
	 *  \param j : coordonnée ("ordonnée") de la valeur cherchee dans la matrice
	 *  \return Retourne la valeur de la matrice en (i,j)
	 */	
		float getValeur  ( int i, int j );
		
	/*!
	 *  \brief Assigne la valeur de la matrice en (i,j)
	 *
	 *  Methode qui assign la valeur de la matrice en (i,j)
	 *  \param i : coordonnée ("abscisse") de la valeur cherchee dans la matrice
	 *  \param j : coordonnée ("ordonnée") de la valeur cherchee dans la matrice
	 *  \param v : valeur à assigner
	 *  \return void
	 */		
		void setValeur  ( int i, int j, float v );
		
	/*!
	 *  \brief Renvoie la hauteur de la matrice
	 *
	 *  Methode qui renvoie la hauteur de la matrice
	 *  \return Retourne la la hauteur de la matrice
	 */	
		float getHauteur  ();
		
	/*!
	 *  \brief Renvoie la largeur de la matrice
	 *
	 *  Methode qui renvoie la largeur de la matrice
	 *  \return Retourne la la largeur de la matrice
	 */	
		float getLargeur  ();
		
	/*!
	 *  \brief Calcule la transposée de la matrice
	 *
	 *  Methode qui calcule la transposée de la matrice
	 *  \param m : pointeur vers la matrice a transposer
	 *  \return Retourne un pointeur vers la matrice transposée.
	 */			
		Matrice* transposee ( Matrice* m );
		Matrice* transposee ( );
		
	/*!
	 *  \brief Calcule matrice . matriceTransposee
	 *
	 *  Si matrice en entrée a n lignes et m colonnes, alors la matrice
	 *	résultante aura n lignes et n colonnes.
	 *  \param _res pointeur vers la matrice résultat (si NULL, la matrice est créée)
	 *  \return Retourne un pointeur vers la matrice résultat
	 */		
		Matrice * mmT ( Matrice * _res = NULL );

	/*!
	 *  \brief Calcule matrice . matriceTransposee
	 *
	 *  Si matrice en entrée a n lignes et m colonnes, alors la matrice
	 *	résultante aura n lignes et n colonnes.
	 *	Version optimisée (en mémoire et en temps) de mmT ().
	 *	Ne fonctionne que pour un vecteur de taille 2 en entree.
	 *  \param _res pointeur vers la matrice résultat (si NULL, la matrice est créée)
	 *  \return Retourne un pointeur vers la matrice résultat
	 */		
		Matrice * mmT2 ( Matrice * _res = NULL );

	/*!
	 *  \brief Calcule le determinant d'une matrice
	 *
	 *  Methode qui calcule le determinant d'une matrice
	 *  \return Retourne la valeur du determinant de la matrice
	 */			
		float determinant ();
		
	/*!
	 *  \brief Normalise la matrice de 1 colonne et n lignes
	 *
	 *	norm = sum ( Ai*Ai );
	 *  AiNew := Ai / norm;
	 *  \return Retourne la valeur du determinant de la matrice
	 */	
		void normaliserVecteur ();
	
	/*!
	 *  \brief Permet d'afficher une matrice sous la console
	 *
	 *  Methode qui affiche les coefficients d'une matrice sous la console
	 *  \return Ne retourne rien
	 */	
		void afficher ();
	

		float** matrice;
		int largeur;
		int hauteur;
};
#endif
